package Chess.Moves;

import java.util.Arrays;
import java.util.List;
import java.awt.Color;
import Chess.*;
import Chess.Pieces.*;
import Chess.Pieces.Piece.*;

/**
 *	A class representing a PromotionMove in Chess.
 *
 *	@author		Jeff Chan
 */
public class PromotionMove extends Move {

	private static List<PieceType> promotionPieceTypes = 
		Arrays.asList(new PieceType[] {PieceType.QUEEN, PieceType.ROOK, PieceType.BISHOP, PieceType.KNIGHT});
	
	private Piece promotionPiece;
	private Piece opposingPiece;
	
	public PromotionMove(Piece piece, Square startSquare, Square promotionSquare, Piece promotionPiece, Piece opposingPiece) {
		super(piece, startSquare, promotionSquare);
		this.promotionPiece = promotionPiece;
		this.opposingPiece = opposingPiece;
	}
	
	public MoveType getMoveType() {
		return MoveType.PROMOTION;
	}

	public void undo(Board board) {
		board.removePiece(endSquare);
		if (opposingPiece != null) {
			board.putPiece(endSquare, opposingPiece);
		}
		board.putPiece(startSquare, piece);
	}

	public static boolean canBeExecuted(Board board, Square startSquare, Square endSquare, PieceType pieceType) {
		boolean canBeExecuted = false;
		
		if (board != null) {
			Piece piece = board.getPiece(startSquare);
			if (piece != null && PieceType.PAWN.equals(piece.getPieceType()) 
				&& promotionPieceTypes.contains(pieceType) && endSquare.isInLastRow(piece.getColor())) {
				if (piece.canMove(board, startSquare, endSquare) ||
					piece.canAttack(board, startSquare, endSquare)) {
					canBeExecuted = true;
				}
			}
		}

		return canBeExecuted;
	}

	public static Move execute(Board board, Square startSquare, Square endSquare, PieceType pieceType) {
		Piece piece = board.getPiece(startSquare);
		Piece promotionPiece = createPromotionPiece(pieceType, piece.getColor());
		Piece opposingPiece = null;
		
		if (board.hasPiece(endSquare)) {
			opposingPiece = board.getPiece(endSquare);
			board.removePiece(endSquare);
		}	
		board.removePiece(startSquare);
		board.putPiece(endSquare, promotionPiece);
		
		return new PromotionMove(piece, startSquare, endSquare, promotionPiece, opposingPiece);
	}
	
	public Piece promotionPiece() {
		return promotionPiece;
	}
	
	public Piece getOpposingPiece() {
		return opposingPiece;
	}

	private static Piece createPromotionPiece(PieceType pieceType, Color color) {
		Piece promotionPiece = null;
		
		if (PieceType.QUEEN.equals(pieceType)) {
			promotionPiece = new Queen(color);
		} else if (PieceType.ROOK.equals(pieceType)) {
			promotionPiece = new Rook(color);
		} else if (PieceType.BISHOP.equals(pieceType)) {
			promotionPiece = new Bishop(color);
		} else if (PieceType.KNIGHT.equals(pieceType)) {
			promotionPiece = new Knight(color);
		}
		
		return promotionPiece;
	}

}
